package com.ls.datasource;

import org.apache.ibatis.io.VFS;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Configuration
@AutoConfigureAfter(DataSourceConfiguration.class)
@MapperScan(basePackages="com.ls.mapper")
//@PropertySource(value = {"classpath:application.yml"},ignoreResourceNotFound = true)
public class MybatisConfiguration {

	private Logger log = LoggerFactory.getLogger(MybatisConfiguration.class);

	@Value("${mysql.datasource.readSize}")
    private String readDataSourceSize;

//	//XxxMapper.xml文件所在路径
	  @Value("${mysql.mapperLocations}")
      private String mapperLocations;
//
//     //  加载全局的配置文件
      @Value("${mysql.configLocation}")
      private String configLocation;

      @Value("${mysql.typeAliasPackage}")
      private String typeAliasPackage;


    @Bean(name="sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactorys(@Qualifier("masterDataSource") DataSource masterDataSource,
                                                @Qualifier("slave1DataSource") DataSource slave1DataSource,
                                                @Qualifier("slave2DataSource") DataSource slave2DataSource) throws Exception {
        log.info("--------------------  sqlSessionFactory init ---------------------");
        try {
            VFS.addImplClass(SpringBootVFS.class);
            SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
       //     sessionFactoryBean.setDataSource(roundRobinDataSouce);
//            sessionFactoryBean.setDataSource(masterDataSource);
            sessionFactoryBean.setDataSource(roundRobinDataSouceProxy(masterDataSource,slave1DataSource,slave2DataSource));

            // 读取配置
//            sessionFactoryBean.setTypeAliasesPackage("com.fei.springboot.domain");

            //设置mapper.xml文件所在位置
            Resource[] resources = new PathMatchingResourcePatternResolver().getResources(mapperLocations);
            sessionFactoryBean.setMapperLocations(resources);
//            sessionFactoryBean.setTypeAliasesPackage(typeAliasPackage);

         //设置mybatis-config.xml配置文件位置
            Resource resource = new PathMatchingResourcePatternResolver().getResource(configLocation);
            sessionFactoryBean.setConfigLocation(resource);

//            XMLConfigBuilder xmlConfigBuilder = new XMLConfigBuilder(resource.getInputStream(), null);
//            sessionFactoryBean.setConfiguration(xmlConfigBuilder.getConfiguration());
//            sessionFactoryBean.setConfigLocation(resource);

//            log.info("ssss" + ((xmlConfigBuilder.getConfiguration() == null && resource == null) || !(xmlConfigBuilder.getConfiguration() != null && resource != null)));
            log.info("init sessionFactory complete");

            return sessionFactoryBean.getObject();
        } catch (IOException e) {
            log.error("mybatis resolver mapper*xml is error",e);
            e.printStackTrace();
            return null;
        } catch (Exception e) {
            log.error("mybatis sqlSessionFactoryBean create error",e);
            return null;
        }
    }


    /**
     * 把所有数据库都放在路由中
     * @return
     */
    @Bean(name="roundRobinDataSouceProxy")
    public AbstractRoutingDataSource roundRobinDataSouceProxy(@Qualifier("masterDataSource") DataSource masterDataSource,
                                                              @Qualifier("slave1DataSource") DataSource slave1DataSource,
                                                              @Qualifier("slave2DataSource") DataSource slave2DataSource) {

    	Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
        //把所有数据库都放在targetDataSources中,注意key值要和determineCurrentLookupKey()中代码写的一至，
        //否则切换数据源时找不到正确的数据源
        targetDataSources.put(DataSourceType.MASTER.getCode(), masterDataSource);
        targetDataSources.put(DataSourceType.SLAVE.getCode()+"1", slave1DataSource);
        targetDataSources.put(DataSourceType.SLAVE.getCode()+"2", slave2DataSource);


        final int readSize = Integer.parseInt(readDataSourceSize);
        //     MyAbstractRoutingDataSource proxy = new MyAbstractRoutingDataSource(readSize);

        //路由类，寻找对应的数据源
        DynamicDataSource proxy = new DynamicDataSource();

        proxy.setDefaultTargetDataSource(masterDataSource);//默认库
        proxy.setTargetDataSources(targetDataSources);

        proxy.afterPropertiesSet();

        return proxy;
    }


    @Bean(name = "sqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory")SqlSessionFactory sqlSessionFactory) {
        log.info("init sqlSessionTemplate, sqlsessionFactory:" + sqlSessionFactory);
        log.info("init sqlSessionTemplate, sqlsessionFactory:" + sqlSessionFactory.getConfiguration());
    	return new SqlSessionTemplate(sqlSessionFactory);
    }

    //事务管理
    @Bean
    public PlatformTransactionManager annotationDrivenTransactionManager(@Qualifier("roundRobinDataSouceProxy") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

}
